package com.cnkvha.trackcontestmgmt;

import com.cnkvha.trackcontestmgmt.contest.Contest;
import com.cnkvha.trackcontestmgmt.contest.ContestState;
import com.cnkvha.trackcontestmgmt.ui.ControlWindow;
import com.cnkvha.trackcontestmgmt.web.TCMWebSocketHandler;
import org.webbitserver.WebServer;
import org.webbitserver.WebServers;
import org.webbitserver.handler.StaticFileHandler;

import java.io.File;
import java.io.FileInputStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class TrackContestManagement {

    public static final TrackContestManagement instance = new TrackContestManagement();

    public static void main(String[] args) {
        instance.start();
    }

    private LoggerThread logger;

    private ExecutorService executor = Executors.newSingleThreadExecutor();

    private ApplicationSettings settings;

    private ControlWindow window;
    private WebServer web;
    private TCMWebSocketHandler webSocketHandler;

    private ContestDataManager contestDataManager;

    private Contest currentContest;


    public LoggerThread getLogger() {
        return logger;
    }

    public ControlWindow getControlWindow() {
        return window;
    }

    public WebServer getWebServer() {
        return web;
    }

    public TCMWebSocketHandler getWebSocketHandler() {
        return webSocketHandler;
    }

    private void start() {
        window = new ControlWindow();

        logger = new LoggerThread();
        logger.start();
        logger.log("启动中... ");
        logger.log("========");
        logger.log("开发者: ");
        logger.log("Kevin Wang");
        logger.log("作曲系 - 2016级本科");
        logger.log("首都师范大学音乐学院");
        logger.log("========");

        logger.log("读取比赛数据中... ");
        contestDataManager = new ContestDataManager(new File("contests"));
        logger.log("比赛数据完成! ");

        window.postInit();

        if(ResourceUtil.saveResource("settings.yml", false)) {
            logger.log("生成了新的配置文件! ");
        }

        logger.log("读取配置文件中... ");
        new File("contests").mkdirs();
        try {
            File settings_file = new File("settings.yml");
            if (settings_file.exists() && settings_file.isFile()) {
                settings = new org.yaml.snakeyaml.Yaml().loadAs(new FileInputStream(settings_file), ApplicationSettings.class);

                UserType.BEGIN.setAllowedIdentifiers(settings.identifiers_begin);
                UserType.TIMER.setAllowedIdentifiers(settings.identifiers_timer);
                UserType.RECTIFIER.setAllowedIdentifiers(settings.identifiers_rectifier);

                UserType.BEGIN.setPassword(settings.pwd_begin);
                UserType.TIMER.setPassword(settings.pwd_timer);
                UserType.RECTIFIER.setPassword(settings.pwd_rectifier);

                logger.log("成功加载配置! ");
            } else {
                logger.log("配置文件未找到，加载了默认。");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.log("读取配置出错，加载了默认。");
        }

        logger.log("启动Web服务中... ");
        web = WebServers.createWebServer(80);
        webSocketHandler = new TCMWebSocketHandler(web);
        web.add("/connect", webSocketHandler);
        web.add(new StaticFileHandler("web"));
        web.start();
    }

    public ContestDataManager getContestDataManager() {
        return contestDataManager;
    }

    public Contest getCurrentContest() {
        return currentContest;
    }

    public boolean isCurrentContestSet() {
        return currentContest != null;
    }

    public boolean setCurrentContest(Contest currentContest) {
        if(this.currentContest != null && (this.currentContest.state == ContestState.TRACKING || this.currentContest.state == ContestState.WAITING)) {
            log("不能在比赛途中切换比赛! ");
            return false;
        }
        if(this.currentContest != null) {
            this.currentContest.resetRuntimeData();
        }
        queueOnOperationThread(() -> {
            this.currentContest = currentContest;

            getWebSocketHandler().resetAllStates();
            getWebSocketHandler().broadcastValidClients("reset;" + (this.currentContest != null ? this.currentContest.name : ""));

            window.markRefresh();
        });

        return true;
    }

    public Future queueOnOperationThread(Runnable task) {
        if(task == null) return null;
        return executor.submit(task);
    }

    public static void log(String text) {
        instance.logger.log(text);
    }

    public static void log(String text, Object... params) {
        instance.logger.log(text, params);
    }
}
